﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace InternetSpiderLib
{
    /// <summary>
    /// 业务管理
    /// </summary>
    public class BusinessManager
    {
        private Thread[] ThreadItems = null;
        private Thread ManagerThread = null;

        private bool IsRuning = false;

        private AutoResetEvent ResetEvent = new AutoResetEvent(false);

        private int FreeCount { get { return ThreadItems?.Count(n => n == null || n.ThreadState == ThreadState.Stopped) ?? 0; } }

        public IBusinessCreater BusinessCreater { get; set; }

        private int BusinessInterval { get; set; } = 5000;

        public int BusinessDelay { get; set; } = 0;

        public BusinessManager(uint count)
        {
            if (count == 0)
                throw new Exception("线程个数必须是正整数");

            ThreadItems = new Thread[count];
        }

        /// <summary>
        /// 开始业务
        /// </summary>
        public void Start()
        {
            if (BusinessCreater == null)
                throw new Exception($"开始之前必须初始化 {nameof(BusinessCreater)}");

            if (ManagerThread != null)
                throw new Exception("不允许重复开启托管逻辑");

            ManagerThread = new Thread(() => { BusinessMethod(); }) { IsBackground = true };
            ManagerThread.Start();
        }

        /// <summary>
        /// 停止业务
        /// </summary>
        public void Stop()
        {
            IsRuning = false;
            ResetEvent.Set();
            ManagerThread?.Join();
        }

        public void Wait()
        {
            ManagerThread?.Join();
        }

        /// <summary>
        /// 业务函数
        /// </summary>
        private void BusinessMethod()
        {
            IsRuning = true;
            while (true)
            {
                while (FreeCount == 0 && IsRuning)
                    ResetEvent.WaitOne(BusinessInterval);

                if (IsRuning == false)
                    break;

                Action action = null;
                while ((action = BusinessCreater?.Create()) == null && IsRuning)
                    ResetEvent.WaitOne(BusinessInterval);

                if (IsRuning == false)
                    break;

                for (int i = 0; i < ThreadItems.Length; i++)
                {
                    if (ThreadItems[i] != null && ThreadItems[i].ThreadState != ThreadState.Stopped)
                        continue;

                    if (BusinessDelay > 0)
                        Thread.Sleep(BusinessDelay);

                    int index = i;
                    ThreadItems[i] = new Thread(() =>
                    {
                        try
                        {
                            action();
                        }
                        catch (Exception)
                        {

                        }

                        ThreadItems[index] = null;
                        ResetEvent.Set();
                    });
                    ThreadItems[i].Name = i.ToString();
                    ThreadItems[i].Start();
                    break;
                }
            }

            while (ThreadItems?.All(n => n == null || n.ThreadState == ThreadState.Stopped) ?? false)
                Thread.Sleep(100);
        }
    }
}
